﻿using System;
using System.Collections.ObjectModel;

namespace System.Data
{
    public class BindableObjectCollection : ObservableCollection<object>
    {
        #region Data Fields
        /// <summary>
        /// Holds deleted bindable objects
        /// </summary>
        private Collection<BindableObject> _deletedBindableObjects;
        #endregion

        #region Events
        /// <summary>
        /// Add record request
        /// </summary>
        internal event EventHandler<EventArgs> AddRecord;
        #endregion

        #region Constructors
        public BindableObjectCollection()
        {
            this._deletedBindableObjects = new Collection<BindableObject>();
        }
        #endregion

        #region Methods
        /// <summary>
        /// Adds bindable object to collection
        /// </summary>
        /// <param name="bindableObject">Bindable object for adding</param>
        /// <returns>Added bindable object</returns>
        internal BindableObject Add(BindableObject bindableObject)
        {
            bindableObject.DeleteFromCollection += new EventHandler<EventArgs>(BindableObject_DeleteFromCollection);
            bindableObject.RemoveFromCollection += new EventHandler<EventArgs>(BindableObject_RemoveFromCollection);
            base.Add(bindableObject);
            base.OnCollectionChanged(new System.Collections.Specialized.NotifyCollectionChangedEventArgs(System.Collections.Specialized.NotifyCollectionChangedAction.Reset));
            return bindableObject;
        }

        /// <summary>
        /// Adds empty bindable object
        /// </summary>
        public void Add()
        {
            if (AddRecord != null)
            {
                AddRecord(this, new EventArgs());
            }
        }

        /// <summary>
        /// Deletes selected bindable objects
        /// </summary>
        public void Delete()
        {
            for (int i = 0; i < base.Count; i++)
            {
                // Get next bindable object
                BindableObject bindableObject = (BindableObject)base[i];
                if (bindableObject.GetSelected())
                {
                    // Set Deleted on bindable object and add it to temporary storage
                    bindableObject.SetDeleted();
                    this._deletedBindableObjects.Add(bindableObject);
                }
            }

            // Remove bindable object from display
            for (int i = 0; i < this._deletedBindableObjects.Count; i++)
            {
                base.Remove(this._deletedBindableObjects[i]);
            }

            // Clear temporary storage
            this._deletedBindableObjects.Clear();
        }

        /// <summary>
        /// Rejects all changes
        /// </summary>
        public void RejectChanges()
        {
            // Undo editing
            for (int i = 0; i < base.Count; i++)
            {
                ((BindableObject)base[i]).RejectChanges();
            }
/*
            // Undo deletion
            for (int i = 0; i < this._deletedBindableObjects.Count; i++)
            {
                base.Add(this._deletedBindableObjects[i]);
            }

            this._deletedBindableObjects.Clear();
*/
        }

        /// <summary>
        /// Removes bindable object from collection
        /// </summary>
        /// <param name="bindableObject">Bindable object for removing</param>
        internal void Remove(BindableObject bindableObject)
        {
            bindableObject.RemoveFromCollection -= BindableObject_RemoveFromCollection;
            base.Remove(bindableObject);
            base.OnCollectionChanged(new System.Collections.Specialized.NotifyCollectionChangedEventArgs(System.Collections.Specialized.NotifyCollectionChangedAction.Reset));
        }
        #endregion

        #region Event Handlers
        /// <summary>
        /// Handles BindableObject.DeleteFromCollection event
        /// </summary>
        /// <param name="sender">Event source</param>
        /// <param name="e">Event arguments</param>
        void BindableObject_DeleteFromCollection(object sender, EventArgs e)
        {
            BindableObject bindableObject = (BindableObject)sender;
            this._deletedBindableObjects.Add(bindableObject);
            this.Remove(bindableObject);
        }

        /// <summary>
        /// Handles BindableObject.RemoveFromCollection event
        /// </summary>
        /// <param name="sender">Event source</param>
        /// <param name="e">Event arguments</param>
        void BindableObject_RemoveFromCollection(object sender, EventArgs e)
        {
            this.Remove((BindableObject)sender);
        }
        #endregion
    }
}
